The format of this document is for people who have the most recent version.
The most current information is at the top.  If you are not familiar with
Dynamo, or if you have skipped a version or two, you may want to read the
information here in a different order than presented.


_______________________________________________________________________________


Dynamo 4.2 information:

There are only a few difference between 4.1 and 4.2.  The first is a small
change in the ascii-to-int functions.  A - sign was allowed as the first
character, but a + sign was not.  This caused ascii string starting with a
+ sign to immediately abort calculating the value, since the very first
character was not correct.  This has been changed.  The + sign is simply
ignored, and processing continues from the character after the + sign.

The second change is the addition of initial segment support.  Basically,
everything works the same for transferring blocks of code/data, except
that after moving the block, the block can be optionally called now.  This
allows segments to be used to initialize stuff and then not be used again,
thus freeing up the memory that those segments occupied.

The third change is support for GSBUG.  GSBUG needs 4 pages of consecutive
RAM in the primary 48k of memory.  This new feature allows you to designate
where this 1024 bytes of RAM is to start.

For more information on the initial segment support and the GSBUG support,
see the file "buildapp.manual.text".


_______________________________________________________________________________


Dynamo 4.1 information:

BUILDAPP.SYSTEM didn't handle building an application that had auxiliary 48K
memory segments.  This has been fixed.

There were a couple of floating-point problems.  f2i left error-trapping on,
which is very bad, since the error-trapping waits for any character to be
printed.  (This is the only way to trap AppleSoft floating-point errors.)

The startBinary routine called startBinary0.  This made the depth of the stack
other than 2 rts's, which is wrong for the way error-trapping works.  This
has been fixed.

The floating-point random number generator rfnd was sick.  It is better now.


_______________________________________________________________________________


Dynamo 4.0 information:

The big addition to Dynamo for the 4.0 version is floating-point support.
The implementation uses the AppleSoft ROM routines.  This allows the
implementation to remain small, which is one of Dynamo's trademarks.
Any computational error is trapped, and flow-of-control is returned to
the application, with the carry set, and the error code in the accumulator.

The implementation has no impact on page-zero utilization.  The zero-page
and stack are preserved prior to any AppleSoft ROM call, so in the case of
an error, the stack can be recovered, and in either case, zero-page can be
restored.

The array handling was changed to accomodate the additional data size of
5 bytes.  The size parameter of the array macro was changed from being
either a 'b' or a 'w' (for byte or word) to the physical size of an element.
Note that there is now no restriction for sizes other than 1, 2 or 5 bytes.
An element can be any size.  Of course, for sizes other than 1, 2, or 5
bytes, you will have to supply your own array element access routines.

An attempt has been made to keep the syntax for floating-point as consistent
as possible with the way integers were handled.  For the most part, floating-
point macros start with _f.  This isn't always true .  There are some logical
exceptions.  Once such exception is for converting an integer into a float.
This macro is called _i2f, and the reverse function is called _f2i.  So,
although there is no steadfast rule, the rule is consistent and logical enough
to be useful.

Also, a change has been made to the variable space.  There can now be two
variable spaces.  One of the variable spaces is the same old integer variable
space.  The other, logically enough, is for floating-point numbers.  These
two variables spaces can be the same 256 bytes (mixing floats with ints), or
they can be separate 256 byte areas.  If they are the same space, then _i2f
and _f2i convert the value in place.  If they are different spaces, then the
value is converted and copied to the other variable space.  (What this means
is that if you have two different variable spaces, you can have both an
integer and a floating-point value for the same variable.  Weird.)

The same variable name (read same offset) is used into the variable space(s)
for both the source and destination of the conversion, even if you have two
variables spaces.  I now think that this may have been a mistake.  In any case,
that is how it stands currently.  I may change this in the future.  The
reasoning for this (I did have a reason for the current implementation) was
that a program probably didn't have all that many floating-point numbers, and
would probably be using the one-variable-space model.  Now I think that I
should have implemented _i2f and _f2i so that they took two variable names,
instead of just one as they do now.  With two variable names, I could designate
a destination variable that is different than the source variable.  This would
probably be more useful for a greater range of uses.  (Oh well.)


_______________________________________________________________________________


Dynamo 3.1 information:



I have been busy changing things for no reason at all, and here's where I stand:
(This is a joke.  I had reasons.  I just can't remember what they were.)
((This is a joke.))


1)	BUILDAPP.SYSTEM has changed.  The new build script sample looks like this:

DUMMY							;The default script filename.
0,$0800,SAMPLE.BIN				;Sample app, segment 1 (on server).
0,$8000,SAMPLE.BIN.2			;Sample app, segment 2 (on server).
0,$9000,SAMPLE.BIN.3			;Sample app, segment 3 (on server).
$80,$800						;Starting address.
$								;Display starting address in hex.
$								;Display application size in hex.
N								;Skip save file prompt (and don't save it).
$FF,0,SAMPLE.SYSTEM				;Target filename, filetype, and auxtype.

The difference is the 8th line.  This is new.  You don't have to be prompted from
the keyboard anymore.  You can put a Y,N, or Q here instead of typing it.  If you
don't put one of these letters (lowercase is okay, too), then you will be prompted
from the keyboard.  As a convention, I recommend a ? if you want to be prompted.


2)	The runtime and macros have been revised a few times lately.  One of these
	changes was to optimize _decout, _add, _sub, _mul, _div, _set, _index,
	_getb, _getw, _putb, and _putw.  This was a bad idea, since it makes it
	even more difficult to do Dynamo versions for other assemblers and keep
	them as compatible as possible.  This feature in the MPW version caused
	a greater leel of incompatibility, so I have removed it.  There is a
	benefit that remained.  There were some entry points added for the array
	indexing and accessing routines for the optimizations.  These entry points
	are still there.  Given that _index, _getb, _getw, _putb, and _putw are no
	longer figuring out which entry point to call, there have been some macros
	added.  These are (logically enough) _indexl, _getbl, _getwl, _putbl, and
	_putwl.  These don't load a 2-byte constant into the accumulator and
	y-register.  Rather, they load a one byte value into the accumulator and
	then call the alternate entry point (which loads the accumulator with 0
	and branches to the regular entry point).  If you have a constant in the
	range 0-255, as an optional syntax, you can still call _getb, _getw, _putb,
	and _putw, as long as you put a < in the constant parameter to indicate it
	is a 1-byte value.  For _index, this is the ONLY way to just load the
	accumulator and call the alternate entry point.  There is no _indexl
	macro.  The reason for this is that you can have multiple indexes for
	one instance of _index, so each parameter needs to demonstrate if it is
	a 1-byte or 2-byte value.  Some syntax examples would be:
		_index		#345,,<#3
		_getw		var1,<#3

	A constant parameter can now take these following forms and it produces
	the following code:
		1)	= #constant
				lda #<constant
				ldy #>constant
		2)	= *address
				lda address
				ldy address+1
		3)	= #<constant
				lda #<constant
		4)	= *<address
				lda address

	As a sample we want to calculate the number of bytes necessary to store a
	rectangle of data on the screen.  We have a rectangle stored at $4000, in
	the form x1,y1,x2,y2.  The x-values take two bytes (0-280), and the y-values
	take 1 byte (0-192).  How many bytes do this take?
		First, we calculate which row we are starting in.

		The formula is:  bytes = (int((x2 + 6) / 7) - int(x1 / 7) * (y2 - y1)
		The macros to do this formula would look like:

			rect	equ		$4000
			x1		equ		0
			y1		equ		2
			x2		equ		3
			y2		equ		5

	1)				_set	temp,*rect+x1		;temp = x1
	2)				_div	,#<7				;temp = int(x1 / 7)
	3)				_set	bytes,*rect+x2		;bytes = x2
	4)				_add	,#<6				;temp = x2 + 6
	5)				_div	,#<7				;bytes = int((x2 + 6) / 7)
	6)				_subvar	,temp				;bytes = bytes - temp
												;We now have # of bytes wide (in bytes).
	7)				_set	temp,*<rect+y2		;temp = y2
	8)				_sub	,*<rect+y1			;temp = y2 - y1
	9)				_mul	bytes,temp			;bytes = bytes * temp

		The code for these macros would look like:
	1)				ldx		#temp
					lda		rect+x1
					ldy		rect+x1+1
					jsr		setcon				;Set temp to a 2-byte value.

	2)				lda		#<7
					jsr		divconl				;Divide temp by a 1-byte constant.

	3)				ldx		#bytes
					lda		rect+x2
					ldy		rect+x2+1
					jsr		setcon				;Set bytes to a 2-byte value.

	4)				lda		#<6
					jsr		addconl				;Add a 1-byte constant to bytes.

	5)				lda		#<7
					jsr		divconl				;Divide bytes by a 1-byte constant.

	6)				ldy		#temp
					jsr		subvar				;Subtract temp from bytes.

	7)				ldx		#temp
					lda		rect+y2
					jsr		setconl				;Set temp to a 1-byte value.

	8)				lda		rect+y1
					jsr		subconl				;Subtract a 1-byte value from temp.

	9)				ldx		#bytes
					ldy		#temp
					jsr		mulvar				;bytes = bytes * temp

		Since the y-values are only 1 byte, it is less code to write steps 7-9 like this:
					lda		rect+y2
					sec
					sbc		rect+y1
					_mull
		Note that bytes didn't have to be redeclared for the multiply.  It is still
		around from step 3.  (Steps 4 thru 6 start with a comma, thus leaving the
		x-register alone.)  Also note that we said _mull, NOT _mul.  Since we are
		not stating what we are multiplying by, we aren't telling the macros how
		big the value is.  Since it doesn't know, it has to assume we know what we
		are doing.  If we said _mul, it would assume that we wanted to multiply by
		a 2-byte value, and the y-register would hold the hi-byte.  That isn't what
		we want in this case.  We want to multiply by a 1-byte value, so we have to
		use the _mull macro instead.  This needs to be watched carefully!! 

		So, we used the macros when it helped (readability and/or code size) and wrote
		regular assembly code when it was easy and smaller.  The best of both worlds!!


3)	Another runtime change that stayed in is a value called strvalcount.  This
	value is calculated by _strval and _midstrval.  strvalcount is the number
	of characters involved in the evaluation of the string value.  Some examples:

		_strval of:  -$100FG							returns -4111 (or 61425) 
														and sets strvalcount to 6.

		_midstrval(from char 4) of:  ------345.6789		returns 345 (two minuses
														cancel each other out) and
														sets strvalcount to 5.

	This addition is very useful when parsing a string.  If you pull an integer
	value from a string, you may want to know how many characters the runtime
	routine used.  If this value wasn't set, you would have to know all of the
	rules that the runtime used to evaluate the integer and walk through the
	string again yourself.  This is wasteful, and also can be a problem if the
	evaluation method is ever changed.  If that occured, you would have to change
	code in more than one place.  strvalcount is not returned in any register.
	The registers are all used already.  Also, you commonly don't care about this
	value.  (When you do care, you need it badly.)  strvalcount is simply a byte
	value that you have external access to.  If you want it, just load it.


4)	Another _strval or _midstrval calculated value is strvaldigit.  This tells
	you if the string evaluation routine actually found any digits.  When you
	are returned a value of 0, you don't know if this was because there was a
	value of 0 (or -$0000 for that matter), or because the routine ran into a
	non-integer character before it could find any characters to evaluate.  The
	strvaldigit value tells you which occured.  It holds the number of digit
	characters encountered.  (If strvaldigit is 0, then the integer result must
	also be 0.)  Note that strvalcount can be greater than 0 even if strvaldigit
	is 0.  This would occur in the string: -$G  In this case strvalcount would be
	2 (the - and the $) and strvaldigit would be 0 (there were no legal digits).


5)	Another change (kind of big, kind of small) is how the variable space is
	defined.  It used to be that varstart was equated in app.config.  If it
	changed, the runtime has to be reassembled and turned into a library again.
	This has been leading to errors that are time consuming to trace.  Instead,
	what is being done is to let the linker worry about it.  There now needs to
	be a varspace space (256 bytes) for the linker to link in.  Once this is
	done, varspace can be kept, or you can use LinkIIGS and MakeBigIIGS to throw
	it away.  The runtime doesn't demand that varspace be part of your program.
	All it cares about is that there are 256 bytes somewhere in memory that it
	will access.  So, it isn't necessary that the application carry these 256
	bytes around.  (Save disk space -- just say no!!)  It is necessary to have
	something for the linker to work with, however.  So, the sample application
	now has an additional segment called varspace.  It is thrown away in this
	example.  This is done by linking it into a separate segment that we don't
	care about.  Check out the make file for exactly how this is done.
	It is worth noting that if you wish to move where the 256-byte varspace
	area is, all you need to do is change the makefile.  Just change the -org
	value for the segment "trash".

6)	More support for indirection and dereferencing has been added.  There are now
	an additional macro for dereferencing, as well as syntax extensions to handle
	multi-level-dereferencing in conjunction with other macros.  Here is some code
	from sample.a that demonstrates the extent of the indirection capabilities:

		_set	var1,**@ptr1		;Set var1 to double-dereferenced @ptr1.
									;var1 has address @ptr3 now.
		_add	,#<2				;Add 2 to the pointer.
		_vderef						;Dereference var1 again (into itself).
									;var1 has address @ptr4 now.
		_vderef						;Dereference var1 again (into itself).
									;var1 has address @ptr5 now.
		_vderef						;Dereference var1 again (into itself).
									;var1 has value from @ptr5 now.
		_vhexout					;Output the variable value (which is $1234)
		jmp		@past

@ptr1		dc.w	@ptr2
@ptr2		dc.w	@ptr3
@ptr3		dc.w	0,@ptr4
@ptr4		dc.w	@ptr5
@ptr5		dc.w	$1234

@past		equ		*




Well, this ought to be enough arbitrary changes for version 3.1 -- have fun.



Eric Soldan, Apple II DTS


_______________________________________________________________________________


Dynamo 3.0 information:

Some new stuff and some cool ideas:

If you are familiar with previous versions of Dynamo, you will see that a
number of things have changed and have been reorganized.  The structure is
more conducive to multiple-project development.  Since Dynamo is localized
and the include files are available to AsmIIGS just like other include files,
Dynamo version control is easier.  It is no longer so tempting to make a
simple custom change to the Dynamo run-time for just one application, and
therefore end up with multiple versions of Dynamo for different projects.

Another big change is that the source code for BUILDAPP.SYSTEM is now
included.  This is so that extensions in the application build and launch
process can be done by others to better suit their needs.  Currently,
BUILDAPP.SYSTEM simply moves the code to the bank and memory location
described in the build script.  Some more complex methods might be needed
for more complex applications.  An application may need overlays, for
example.  There may be two blocks of code that actually need to run at
the same location, just at different times.  A revised BUILDAPP.SYSTEM
could put these so-designated segments in auxiliary memory, and then the
application could move them to main memory when needed.

For example:  Here is a simple idea for an overlay system:

BUILDAPP.SYSTEM could move designated files to aux ram when it is moving
segments around at application launch time.  This could even be done by
using ProDOS to save the range of memory to /RAM5.  When the main
application needs the code segment, it could simply use ProDOS to load it
into main memory.

Here's a reasonably simple approach to overlays:  When you want to call
a segment of code that may or may not be in main memory, do a JSR to 
an overlay management routine.  (Dynamic segments kind of work this way
on the IIGS.)  The code would look something like:

        sec                     ;Input for overlay code.
        lda     value           ;Input for overlay code.
        ldy     value+1         ;Input for overlay code.
        ldx     mode            ;Input for overlay code.

        jsr     overlay
        dc.b    jiffyCoolCode   ;Segment # we want to call.

The overlay manager would first save the registers and processor status.
Then it would use the return address on the stack to figure out where the
jiffyCoolCode segment number is in memory.  It would then get this byte
from memory.  Once this is done, the return address would be incremented 
by 1 and pushed back onto the stack.

Now that we have the overlay segment #, we would use this to load the
segment from /RAM5.  Once it is loaded, the registers and processor status
would be put back to what they were when the overlay manager was called.
Once this is done, the overlay manager would jump to where the code was
loaded.

A little more logic could be added to see if the code segment requested
is already in main memory.  (Old segment # = requested segment #.)  If
it is, then the loading of the code could be skipped.

As you can see, doing overlays isn't so tough after all.  A simple
system like this can really free up a lot of main ram on an Apple II.

For more readability, a macro could be used to call the overlay code.
The call might look like:

        _jsr    jiffyCoolCode

The macro would expand to the calling convention shown above.

Any rate, given that BUILDAPP.SYSTEM isn't the final solution for
everybody, I supplied the code so that everybody could change it
if they wanted to.


Eric Soldan, Apple II DTS
